#include "libdwinpt.h"
#include "libdwinport.h"
#include "crc16.h"
#include "stdlib.h"

dwExport dw_frame_reg_t pdfr;
dwExport dw_frame_var_t pdfv;
dwExport dw_frame_reg_t psdfr;
dwExport dw_frame_var_t psdfv;
dwExport dw_frame_var_wr_t psdfvwr;

dwVOID	dwSendData(dwU8 *data,dwU8 length);
dwBOOL dwWaitRecv(dwVOID);

dwBOOL dwVarTrans(dwU16 * objVar,dwU16 * oriVar,dwU8 length)
{
	dwU8 i;
	for(i=0;i<length;i++){
		objVar[i] = WR_D16(oriVar[i]);
	}
	return dwTRUE;
}
dwBOOL dwVarCpy(dwU16 * objVar,dwU16 * oriVar,dwU8 length)
{
	dwU8 i;
	for(i=0;i<length;i++){
		objVar[i] = oriVar[i];
	}
	return dwTRUE;
}

dwBOOL dwRegCpy(dwU8 * objVar,dwU8 * oriVar,dwU8 length)
{
	dwU8 i;
	for(i=0;i<length;i++){
		objVar[i] = WR_D8(oriVar[i]);
	}
	return dwTRUE;
}

dwBOOL dwMemSet(dwVOID * addr,dwU8 value,dwU16 length)
{
	dwU16 i;
	dwU8 *paddr = (dwU8*)addr;
	for(i=0;i<length;i++){
		paddr[i] = 0;
	}
}


dwBOOL dwSysInit(dwVOID)
{
	dw_reg_t reg = dw_regs_get();
	dw_var_t var = dw_vars_get();
	dwU8 i;
	for(i=0;i<dw_reg_num_get();i++){
		reg->value = (dwU8*)malloc(reg->length);
		if(reg->value == 0){
			return dwFALSE;
		}
		dwMemSet(reg->value,0,reg->length);
		reg++;
	}
	for(i=0;i<dw_var_num_get();i++){
		var->value = (dwU16*)malloc(var->length*2);
		
		if(var->value == 0){
			return dwFALSE;
		}
		dwMemSet(var->value,0,var->length*2);
		var++;
	}
}

dwVOID dwRecvProcess(dwVOID)
{
	if(pdfr->fh != WR_D16(DW_FRAMEHEAD)){
		return;
	}
	switch(pdfr->cmd){
		case DW_CMD_READREG:
			dw_reg_write(pdfr->page,pdfr->addr,pdfr->value,pdfv->words);
			break;
		case DW_CMD_WRITEREG:
			break;
		case DW_CMD_READVAR:
			dw_var_transwrite(WR_D16(pdfv->addr),pdfv->value,pdfv->words);
			break;
		case DW_CMD_WRITEVAR:;
			break;
		default:
			return;
	}
}


dwVOID	dwUartReadReg(dwU8 page,dwU8 addr,dwU8 length)
{
	psdfr->fh		=	WR_D16(DW_FRAMEHEAD);
	psdfr->length	=	WR_D8(4);
	psdfr->cmd		=	WR_D8(DW_CMD_READVAR);
	psdfr->page		=	WR_D8(page);
	psdfr->addr		=	WR_D8(addr);
	psdfr->words	=	WR_D8(length);
	dwSendData((dwU8*)psdfr,3+psdfr->length);
}

dwVOID	dwUartWriteReg(dwU8 page,dwU8 addr,dwU8 *value,dwU8 length)
{
	psdfr->fh		=	WR_D16(DW_FRAMEHEAD);
	psdfr->length	=	WR_D8(4+length);
	psdfr->cmd		=	WR_D8(DW_CMD_WRITEVAR);
	psdfr->page		=	WR_D8(page);
	psdfr->addr		=	WR_D8(addr);
	psdfr->words	=	WR_D8(length);
	dwRegCpy(psdfr->value,value,length);
	dwSendData((dwU8*)psdfr,3+psdfr->length);
}

dwVOID	dwUartReadVar(dwU16 addr,dwU8 length)
{
	psdfv->fh		=	WR_D16(DW_FRAMEHEAD);
	psdfv->length	=	WR_D8(4);
	psdfv->cmd		=	WR_D8(DW_CMD_READVAR);
	psdfv->addr		=	WR_D16(addr);
	psdfv->words	=	WR_D8(length);
	dwSendData((dwU8*)psdfr,3+psdfr->length);
}

dwVOID	dwUartWriteVar(dwU16 addr,dwU16 *value,dwU8 length)
{
	psdfvwr->fh		=	WR_D16(DW_FRAMEHEAD);
	psdfvwr->length	=	WR_D8(3+length*2);
	psdfvwr->cmd		=	WR_D8(DW_CMD_WRITEVAR);
	psdfvwr->addr		=	WR_D16(addr);
	//psdfvwr->words	=	WR_D8(length);
	dwVarTrans(psdfvwr->value,value,length);
	dwSendData((dwU8*)psdfvwr,3+psdfvwr->length);
}


dwBOOL dw_reg_read(dwU8 page,dwU8 addr,dwU8 *value,dwU8 length)
{
	dw_reg_t reg = dw_regs_get();
	dwU8 i;
	for(i=0;i<dw_reg_num_get();i++){
		if(reg->page == page && reg->addr == addr){
			dwRegCpy(value,reg->value,length<=reg->length?length:reg->length);
			return dwTRUE;
		}
		reg++;
	}
	return dwFALSE;
}

dwBOOL dw_reg_write(dwU8 page,dwU8 addr,dwU8 *value,dwU8 length)
{
	dw_reg_t reg = dw_regs_get();
	dwU8 i;
	for(i=0;i<dw_reg_num_get();i++){
		if(reg->page == page && reg->addr == addr){
			dwRegCpy(reg->value,value,length<=reg->length?length:reg->length);
			return dwTRUE;
		}
		reg++;
	}
	return dwFALSE;
}

dwBOOL dw_var_read(dwU16 addr,dwU16 *value,dwU8 length)
{
	dw_var_t var = dw_vars_get();
	dwU8 i;
	for(i=0;i<dw_var_num_get();i++){
		if(var->addr == addr){
			dwVarCpy(value,var->value,length<=var->length?length:var->length);
			return dwTRUE;
		}
		var++;
	}
	return dwFALSE;
}

dw_var_t dw_var_get(dwU16 addr)
{
	dw_var_t lvar = dw_vars_get();
	dwU8 i;
	for(i=0;i<dw_var_num_get();i++){
		if(lvar->addr == addr){
			return lvar;
		}
		lvar++;
	}
	return 0;
}

dwBOOL dw_var_write(dwU16 addr,dwU16 *value,dwU8 length)
{
	dw_var_t var = dw_vars_get();
	dwU8 i;
	for(i=0;i<dw_var_num_get();i++){
		if(var->addr == addr){
			dwVarCpy(var->value,value,length<=var->length?length:var->length);
			var->change = 1;
			return dwTRUE;
		}
		var++;
	}
	return dwFALSE;
}

dwBOOL dw_var_transwrite(dwU16 addr,dwU16 *value,dwU8 length)
{
	dw_var_t var = dw_vars_get();
	dwU8 i;
	for(i=0;i<dw_var_num_get();i++){
		if(var->addr == addr){
			dwVarTrans(var->value,value,length<=var->length?length:var->length);
			var->change = 1;
			return dwTRUE;
		}
		var++;
	}
	return dwFALSE;
}

dwBOOL dwReadReg(dwU8 page,dwU8 addr,dwU8 *value,dwU8 length)
{
	dwUartReadReg(page,addr,length);
	if(dwWaitRecv() && pdfr->cmd == DW_CMD_READREG){
		dw_reg_read(page,addr,value,length);
		return dwTRUE;
	}else{
		return dwFALSE;
	}
}
dwBOOL dwWriteReg(dwU8 page,dwU8 addr,dwU8 *value,dwU8 length)
{
	dwUartWriteReg(page,addr,value,length);
	if(dwWaitRecv() && pdfr->cmd == DW_CMD_WRITEREG){
		dw_reg_write(page,addr,value,length);
		return dwTRUE;
	}else{
		return dwFALSE;
	}
}

dwBOOL dwReadVar(dwU16 addr,dwU16 *value,dwU8 length)
{
	dwUartReadVar(addr,length);
	if(dwWaitRecv() && pdfr->cmd == DW_CMD_READVAR){
		dw_var_read(addr,value,length);
		return dwTRUE;
	}else{
		return dwFALSE;
	}
}

dwBOOL dwWriteSingleVar(dwU16 addr,dwU16 value)
{
	dwUartWriteVar(addr,&value,1);
	dw_var_write(addr,&value,1);
	if(dwWaitRecv() && pdfr->cmd ==DW_CMD_WRITEVAR){
		return dwTRUE;
	}else{
		return dwFALSE;
	}
}

dwBOOL dwWriteVar(dwU16 addr,dwU16 *value,dwU8 length)
{
	dwUartWriteVar(addr,value,length);
	dw_var_write(addr,value,length);
	if(dwWaitRecv() && pdfr->cmd ==DW_CMD_WRITEVAR){
		return dwTRUE;
	}else{
		return dwFALSE;
	}
}

dwBOOL dwChangePage(dwU16 page)
{
	dwU16 val[2];
	val[0] = (0x5A01);
	val[1] = (page);
	return dwWriteVar(VAR_DISPAGE_ADDR,val,2);
}